﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime;

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Derbster.Domain.Test
{
    [TestClass]
    public class OfficialRosterUnitTest : ContractUnitTest
    {
        private HashSet<Official> _testOfficials;
        private OfficialRoster _testOfficialRoster;
        private CommandManager _commandManager;

        [TestInitialize]
        public void TestInitialize()
        {
            _testOfficials = TestHelper.CreateTestOfficials();
            _testOfficialRoster = new OfficialRoster(null);
            _commandManager = new CommandManager();
            _commandManager.Clear();
        }


        [TestMethod]
        public void TestEquals()
        {
            var newOfficialRoster = new OfficialRoster();
            Assert.IsTrue(newOfficialRoster.Equals(newOfficialRoster));
        }

        [TestMethod]
        public void TestMethodAddSkatingOfficial()
        {
            var official = _testOfficials.Skip(2).First();
            Assert.IsNotNull(official);
            _testOfficialRoster.AddSkatingOfficial(official, OfficialPosition.HeadReferee);
            Assert.IsTrue(_testOfficialRoster.Any(ro => ro.Official == official));
            Assert.IsTrue(_testOfficialRoster.SkatingOfficials.Any(ro => ro.Official == official));
            _commandManager.Undo();
            Assert.IsFalse(_testOfficialRoster.Any(ro => ro.Official == official));
            Assert.IsFalse(_testOfficialRoster.SkatingOfficials.Any(ro => ro.Official == official));
            _commandManager.Redo();
            Assert.IsTrue(_testOfficialRoster.Any(ro => ro.Official == official));
            Assert.IsTrue(_testOfficialRoster.SkatingOfficials.Any(ro => ro.Official == official));
        }

        [TestMethod]
        public void TestMethodAddNonSkatingOfficial()
        {
            var official = _testOfficials.Skip(4).First();
            Assert.IsNotNull(official);
            _testOfficialRoster.AddNonSkatingOfficial(official, OfficialPosition.HeadNso);
            Assert.IsTrue(_testOfficialRoster.Any(ro => ro.Official == official));
            Assert.IsTrue(_testOfficialRoster.NonSkatingOfficials.Any(ro => ro.Official == official));
            _commandManager.Undo();
            Assert.IsFalse(_testOfficialRoster.Any(ro => ro.Official == official));
            Assert.IsFalse(_testOfficialRoster.NonSkatingOfficials.Any(ro => ro.Official == official));
            _commandManager.Redo();
            Assert.IsTrue(_testOfficialRoster.Any(ro => ro.Official == official));
            Assert.IsTrue(_testOfficialRoster.NonSkatingOfficials.Any(ro => ro.Official == official));
        }

        [TestMethod]
        public void TestMethodAddSkatingOfficialWrongPosition()
        {
            bool throws = false;
            var official = _testOfficials.Skip(2).First();
            Assert.IsNotNull(official);
            try
            {
                _testOfficialRoster.AddSkatingOfficial(official, OfficialPosition.HeadNso);
            }
            catch (Exception)
            {
                throws = true;
            }
            Assert.IsTrue(throws);
        }

        [TestMethod]
        public void TestMethodAddNonSkatingOfficialWrongPosition()
        {
            bool throws = false;
            var official = _testOfficials.Skip(2).First();
            Assert.IsNotNull(official);
            try
            {
                _testOfficialRoster.AddNonSkatingOfficial(official, OfficialPosition.HeadReferee);
            }
            catch (Exception)
            {
                throws = true;
            }
            Assert.IsTrue(throws);
        }

        [TestMethod]
        public void TestMethodRemoveSkatingOfficialNotAdded()
        {
            bool throws = false;
            var official = _testOfficials.Skip(2).First();
            var otherOfficial = _testOfficials.Skip(4).First();
            _testOfficialRoster.AddSkatingOfficial(official, OfficialPosition.HeadReferee);
            Assert.IsNotNull(official);
            try
            {
                _testOfficialRoster.RemoveSkatingOfficial(otherOfficial);
            }
            catch (Exception)
            {
                throws = true;
            }
            Assert.IsTrue(throws);
        }

        [TestMethod]
        public void TestMethodRemoveNonSkatingOfficialNotAdded()
        {
            bool throws = false;
            var official = _testOfficials.Skip(2).First();
            var otherOfficial = _testOfficials.Skip(4).First();
            _testOfficialRoster.AddNonSkatingOfficial(official, OfficialPosition.HeadNso);
            Assert.IsNotNull(official);
            try
            {
                _testOfficialRoster.RemoveNonSkatingOfficial(otherOfficial);
            }
            catch (Exception)
            {
                throws = true;
            }
            Assert.IsTrue(throws);
        }

        [TestMethod]
        public void TestMethodAddAndRemoveSkatingOfficial()
        {
            var official = _testOfficials.Skip(2).First();
            Assert.IsNotNull(official);
            var official2 = _testOfficials.Skip(4).First();
            Assert.IsNotNull(official2);
            _testOfficialRoster.AddSkatingOfficial(official, OfficialPosition.HeadReferee);
            _testOfficialRoster.AddSkatingOfficial(official2, OfficialPosition.InsidePackReferee);
            _testOfficialRoster.RemoveSkatingOfficial(official);
            Assert.IsFalse(_testOfficialRoster.Any(ro => ro.Official == official));
            Assert.IsFalse(_testOfficialRoster.SkatingOfficials.Any(ro => ro.Official == official));
            _commandManager.Undo();
            Assert.IsTrue(_testOfficialRoster.Any(ro => ro.Official == official));
            Assert.IsTrue(_testOfficialRoster.SkatingOfficials.Any(ro => ro.Official == official));
            _commandManager.Redo();
            Assert.IsFalse(_testOfficialRoster.Any(ro => ro.Official == official));
            Assert.IsFalse(_testOfficialRoster.SkatingOfficials.Any(ro => ro.Official == official));
        }

        [TestMethod]
        public void TestMethodAddAndRemoveNonSkatingOfficial()
        {
            var official = _testOfficials.Skip(2).First();
            Assert.IsNotNull(official);
            var official2 = _testOfficials.Skip(4).First();
            Assert.IsNotNull(official2);
            _testOfficialRoster.AddNonSkatingOfficial(official, OfficialPosition.HeadNso);
            _testOfficialRoster.AddNonSkatingOfficial(official2, OfficialPosition.ScoreKeeper);
            _testOfficialRoster.RemoveNonSkatingOfficial(official);
            Assert.IsFalse(_testOfficialRoster.Any(ro => ro.Official == official));
            Assert.IsFalse(_testOfficialRoster.NonSkatingOfficials.Any(ro => ro.Official == official));
            _commandManager.Undo();
            Assert.IsTrue(_testOfficialRoster.Any(ro => ro.Official == official));
            Assert.IsTrue(_testOfficialRoster.NonSkatingOfficials.Any(ro => ro.Official == official));
            _commandManager.Redo();
            Assert.IsFalse(_testOfficialRoster.Any(ro => ro.Official == official));
            Assert.IsFalse(_testOfficialRoster.NonSkatingOfficials.Any(ro => ro.Official == official));
        }
    }
}
